package cn.yuxiaoyuan.annotation;

import cn.hutool.core.util.ClassUtil;
import cn.yuxiaoyuan.system.domain.Permission;
import cn.yuxiaoyuan.system.mapper.PermissionMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.*;

import java.io.File;
import java.io.FileFilter;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;

/**
 * 项目已启动就要触发
 */
@Component//交给spring管理  我们才可以注入
public class PermissionScan {
    @Autowired
    private PermissionMapper permissionMapper;
    // 扫描路径包前缀
    private static final String PKG_PREFIX = "cn.yuxiaoyuan.";
    // 扫描路径包后缀
    private static final String PKG_SUFFIX = ".controller";
    /**
     * 去读取【io】你当前系统的java文件【反射】  -- 你可以指定位置
     *    条件  必须是controller   -- 你需要路径()
     * 得到controller.java文件  通过反射获取里面的内容 (注解)
     * 得到注解PreAuthorize里面的内容  （sn name descs）
     * 得到注解 @RequestMapping("/article") get post dle 得到url路径
     * permission
     * 保存数据库  --- 新增是不是就做好了  判断一下是否存在了 修改 sn (一定唯一 且不可以修改)
     */
    public void scanPermission(){
        //找到对应的项目路径
        String path = this.getClass().getResource("/").getPath() + "cn/yuxiaoyuan/";
        File file = new File(path);
        //当前文件夹下面的所有 目录+文件
        File[] files = file.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                return pathname.isDirectory();//排除哪些不是目录的文件
            }
        });

        //的所有的controller的类
        Set<Class> clazzes = new HashSet<>();
        for (File file1 : files) {
            Set<Class<?>> classes = ClassUtil
                    //cn.yuxiaoyuan.article.controller
                    .scanPackageByAnnotation(PKG_PREFIX + file1.getName() + PKG_SUFFIX, RestController.class);
            clazzes.addAll(classes);
        }
        //获取类里面的内容只有循环 里面的class
        for (Class clazz : clazzes) {
            //做反射  只有反射才可以取值

            // 得到类中的所有方法，如果类中没有方法那么结束本次循环
            Method[] methods = clazz.getMethods();
            if (methods == null || methods.length < 1){//如果controller 里面没有方法  直接不管
                continue;
            }
            // 3.2.遍历类中的所有方法
            for (Method method : methods) {
                String uri = getUri(clazz, method);
                try {
                    PreAuthorize annotation = method.getAnnotation(PreAuthorize.class);
                    if(annotation == null){
                        continue;
                    }
                    String name = annotation.name();
                    String descs = annotation.descs();
                    String sn = annotation.sn();

                    Permission permission = new Permission();
                    permission.setSn(sn);
                    permission.setUrl(uri);
                    permission.setName(name);
                    permission.setDescs(descs);
                    //判断一下数据库里面有没有
                    Permission permission1 = permissionMapper.selectBySn(sn);
                    if(permission1 == null){
                        //保存数据库
                        permissionMapper.add(permission);
                    }else {
                        BeanUtils.copyProperties(permission,permission1);
                        permissionMapper.update(permission1);
                    }

                }catch (Exception  e){
                    e.printStackTrace();
                }
            }

        }


    }

    /**
     * @Description: 根据类的字节码和类的方法得到方法的请求地址
     * @param clazz: 类字节码对象
     * @param method: 方法对象
     * @return: java.lang.String
     **/
    private String getUri(Class clazz, Method method) {
        String classPath = "";
        Annotation annotation = clazz.getAnnotation(RequestMapping.class);
        if (annotation != null) {
            RequestMapping requestMapping = (RequestMapping) annotation;
            String[] values = requestMapping.value();
            if (values != null && values.length > 0) {
                classPath = values[0];
                if (!"".equals(classPath) && !classPath.startsWith("/")){
                    classPath = "/" + classPath;
                }
            }
        }
        GetMapping getMapping = method.getAnnotation(GetMapping.class);
        String methodPath = "";
        if (getMapping != null) {
            String[] values = getMapping.value();
            if (values != null && values.length > 0) {
                methodPath = values[0];
                if (!"".equals(methodPath) && !methodPath.startsWith("/")){
                    methodPath = "/" + methodPath;
                }
            }
        }
        PostMapping postMapping = method.getAnnotation(PostMapping.class);
        if (postMapping != null) {
            String[] values = postMapping.value();
            if (values != null && values.length > 0) {
                methodPath = values[0];
                if (!"".equals(methodPath) && !methodPath.startsWith("/")){
                    methodPath = "/" + methodPath;
                }
            }
        }
        DeleteMapping deleteMapping = method.getAnnotation(DeleteMapping.class);
        if (deleteMapping != null) {
            String[] values = deleteMapping.value();
            if (values != null && values.length > 0) {
                methodPath = values[0];
                if (!"".equals(methodPath) && !methodPath.startsWith("/")){
                    methodPath = "/" + methodPath;
                }
            }
        }
        PutMapping putMapping = method.getAnnotation(PutMapping.class);
        if (putMapping != null) {
            String[] values = putMapping.value();
            if (values != null && values.length > 0) {
                methodPath = values[0];
                if (!"".equals(methodPath) && !methodPath.startsWith("/")){
                    methodPath = "/" + methodPath;
                }
            }

        }
        PatchMapping patchMapping = method.getAnnotation(PatchMapping.class);
        if (patchMapping != null) {
            String[] values = patchMapping.value();
            if (values != null && values.length > 0) {
                methodPath = values[0];
                if (!"".equals(methodPath) && !methodPath.startsWith("/")){
                    methodPath = "/" + methodPath;
                }
            }
        }
        RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
        if (requestMapping != null) {
            String[] values = requestMapping.value();
            if (values != null && values.length > 0) {
                methodPath = values[0];
                if (!"".equals(methodPath) && !methodPath.startsWith("/")){
                    methodPath = "/" + methodPath;
                }
            }
        }
        return classPath + methodPath;
    }

    public static void main(String[] args) {
        String path = PermissionScan.class.getResource("/").getPath()+"cn/yuxiaoyuan/";
        System.out.println(path);
    }
}
